"""
File: base_page.py
Author: ershixiong
Date: 2023/12/21
describe:

"""
import json
import os
from time import sleep

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

from hogwarts.Wework.utils.log_utils import logger
from hogwarts.Wework.utils.utils import get_root_dir


class BasePage:
    __BASE_URL = 'https://work.weixin.qq.com/'
    __HOME_URL = 'https://work.weixin.qq.com/wework_admin/frame#index'

    def __init__(self, driver=None):
        #  需要判断当前driver是否为空
        if driver:
            self.driver = driver
        else:
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(10)

            if not self.driver.current_url.startswith('http'):
                self.driver.get(self.__BASE_URL)
                self.set_cookies_2()

    def set_cookies_2(self):
        """
        # 先设置cookies
        # 需要判断当前cookies是否失效
        # 因为无法判断企业微信哪个字段控制cookies有效性，可以通过判断是否进入首页来判断是否失效
        # cookies失效的话，需要重新获取然后再设置
        """
        file_path = os.sep.join([get_root_dir(), 'data/cookies.json'])

        if not self.set_cookies_1(file_path):
            # cookies.json文件内容为空时，或者格式错误时，先写入cookies，再设置cookies
            self.write_cookies(file_path)
            self.set_cookies_1(file_path)

        # 设置cookies之后需要重新请求页面，否则不会跳转到对应的页面
        self.driver.get(self.__HOME_URL)

        page_source = self.driver.page_source
        if '首页' not in page_source:
            # cookies.json文件过期后，先写入cookies，再设置cookies
            self.write_cookies(file_path)
            self.set_cookies_1(file_path)

    def set_cookies_1(self, file_path):
        with open(file_path, 'r', encoding='utf-8') as f:
            try:
                cookies = json.load(f)
                for cookie in cookies:
                    self.driver.add_cookie(cookie)
                return True
            except:
                # cookies.json文件为空,或者格式错误时返回False
                return False

    def write_cookies(self, file_path):
        """
        首次登录时或者cookies失效后，写入cookies
        :param file_path:
        :return:
        """
        # 等待区间扫码登录
        sleep(20)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(json.dumps(self.driver.get_cookies()))

    def write_page_source(self, file_path):
        """
        将源码写入文件
        :param file_path: html文件路径
        :return:
        """
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(self.driver.page_source)

    def finds(self, by, locator=None):
        """
        返回多个元素，find_elements即使发现不了元素也不会报错
        :param by:   By.Xpath 或者 (By.Xpath,'xxx')
        :param locator:
        :return:
        """
        if isinstance(by, tuple):
            elements = self.driver.find_elements(*by)
        else:
            elements = self.driver.find_elements(by, locator)
        return elements

    def find(self, by, locator=None):
        """
        返回单个元素
        :param by:   By.Xpath 或者 (By.Xpath,'xxx')
        :param locator:
        :return:
        """
        try:
            return self.finds(by, locator)[0]
        except Exception as e:
            logger.debug(e)

    def element_visible(self, by, locator=None):
        """
        判断元素是否可见
        :param by:   By.Xpath 或者 (By.Xpath,'xxx')
        :param locator:
        :return:
        """
        if isinstance(by, tuple):
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.visibility_of_element_located(by)
                )
                return True
            except:
                return False
        else:
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.visibility_of_element_located((by, locator))
                )
                return True
            except:
                return False

    def element_invisible(self, by, locator=None):
        """
        判断元素是否不可见
        :param by:   By.Xpath 或者 (By.Xpath,'xxx')
        :param locator:
        :return:
        """

        # visible = self.element_visible(by, locator)
        # if not visible:
        #     return True
        # else:
        #     return False

        # 不调用element_visible查看元素是否不可见的原因
        # 当元素不可见时，element_visible会一直查询到时间超时后才返回结果
        # 因此需要单独封装 element_invisible
        if isinstance(by, tuple):
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.invisibility_of_element_located(by)
                )
                return True
            except:
                return False
        else:
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.visibility_of_element_located((by, locator))
                )
                return True
            except:
                return False

    def element_clickable(self, by, locator=None):
        """
        判断元素是否可以点击
        :param by:  By.Xpath 或者 (By.Xpath,'xxx')
        :param locator:
        :return:
        """
        if isinstance(by, tuple):
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.element_to_be_clickable(by)
                )
                return True
            except:
                print('元素不可点击')
                return False
        else:
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.element_to_be_clickable((by, locator))
                )
                return True
            except:
                print('元素不可点击')
                return False

    def find_and_sendkeys(self, locator, value):
        self.find(locator).send_keys(value)

    def find_and_click(self, by, locator=None):
        element = self.find(by, locator)
        if self.element_clickable(by, locator):
            element.click()

    # def wait_element_show(self, click_element, wait_element):
    #     n = 1
    #     while True:
    #         user = self.finds(wait_element)
    #         if len(user) < 1:
    #             ele = self.finds(click_element)
    #             ele[0].click()
    #             n += 1
    #         else:
    #             print(f'点击了{n}次')
    #             break

    def goto_homepage(self):
        # toast提示语消失后，进入首页
        if self.add_toast_invisible() and self.delete_toast_invisible():
            self.driver.get('https://work.weixin.qq.com/wework_admin/frame#index')
            from hogwarts.Wework.pages.home_page import HomePage
            return HomePage(self.driver)

    add_toast = (By.XPATH, '//*[text()="保存成功"]')
    delete_toast = (By.XPATH, '//*[text()="删除成功"]')

    def add_toast_visible(self):
        """
        新增之后，判断是否显示新增成功toast
        :return:
        """
        return self.element_visible(self.add_toast)

    def add_toast_invisible(self):
        """
        新增之后，判断新增成功toast是否消失
        :return:
        """
        return self.element_invisible(self.add_toast)

    def delete_toast_visible(self):
        """
        删除成功之后，判断是否显示删除成功toast
        :return:
        """
        return self.element_visible(self.delete_toast)

    def delete_toast_invisible(self):
        """
        删除成功之后，判断删除成功toast是否消失
        :return:
        """
        return self.element_invisible(self.delete_toast)
